package com.zlsy.thread.future;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * @author zhouliang
 * @date 2020/10/12 20:33
 * 演示future get的超时方法
 * 需要注意超时后处理，调用future.cancel()。演示cancel传入true和false的区别；
 * 代表是否中断正在执行的任务；
 */
@Slf4j
public class FutureGetTimeOut {

    private static final Ad DEFAULT_AD = new Ad("无网络时候的默认广告");
    private static final ExecutorService SERVICE = Executors.newFixedThreadPool(10);

    public void printAd() {
        Future<Ad> f = SERVICE.submit(new FetchAdTask());
        Ad ad;
        try {
            ad = f.get(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            ad = DEFAULT_AD;
            log.error("子线程被中断");
        } catch (ExecutionException e) {
            ad = DEFAULT_AD;
            log.error("子线程异常");
        } catch (TimeoutException e) {
            //超时未获取到广告
            ad = DEFAULT_AD;
            log.error("超时，未获取到广告。");
            boolean cancel = f.cancel(false);
            log.info("f.cancel====>>>{}", cancel);
        } finally {
            SERVICE.shutdown();
        }
        System.out.println(ad);
    }

    static class FetchAdTask implements Callable<Ad> {

        @Override
        public Ad call() throws Exception {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                log.error("sleep interrupted");
                return new Ad("被中断时候的默认广告");
            }
            return new Ad("really");
        }
    }

    static class Ad {
        private String name;

        public Ad(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Ad{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) {
        FutureGetTimeOut futureGetTimeOut = new FutureGetTimeOut();
        futureGetTimeOut.printAd();
    }
}
